'use client';
import GlUtil from '@/lib/glUtils';
import {
	getModeMatrix,
	getPerspectiveViaOrthographic,
	getViewMatrix,
} from '@/lib/WebglUtil';
import { useEffect, useRef } from 'react';
import {
	BufferGeometry,
	Mesh,
	MeshBasicMaterial,
	PerspectiveCamera,
	Scene,
	WebGLRenderer,
	BoxGeometry,
	MeshNormalMaterial,
	Vector3,
	Matrix4,
	BufferAttribute,
} from 'three';
//@ts-ignore
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

function useThreeJs(canvasRef: React.RefObject<HTMLCanvasElement | null>) {
	const rendererRef = useRef<WebGLRenderer | null>(null);
	const sceneRef = useRef<Scene | null>(null);
	const cameraRef = useRef<PerspectiveCamera | null>(null);
	const cubeRef = useRef<Mesh | null>(null);
	const controlsRef = useRef<OrbitControls | null>(null);
	const animationFrameRef = useRef<number>(0);
	// 使用 BufferGeometry 自定义创建立方体的函数
	const createCustomCubeGeometry = () => {
		const geometry = new BufferGeometry();

		// 顶点坐标 (x, y, z)
		const vertices = new Float32Array([
			// 前 (+Z)
			-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0,

			// 后 (-Z)
			1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0,

			// 上 (+Y)
			-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0,

			// 下 (-Y)
			-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,

			// 右 (+X)
			1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0,

			// 左 (-X)
			-1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0,
		]);

		// 法线数据（用于光照计算）
		const normals = new Float32Array([
			// 前
			0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,

			// 后
			0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0,

			// 上
			0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,

			// 下
			0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0,

			// 右
			1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,

			// 左
			-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
		]);

		// 索引（每面两个三角形）
		const indices = [
			0,
			1,
			2,
			2,
			3,
			0, // 前
			4,
			5,
			6,
			6,
			7,
			4, // 后
			8,
			9,
			10,
			10,
			11,
			8, // 上
			12,
			13,
			14,
			14,
			15,
			12, // 下
			16,
			17,
			18,
			18,
			19,
			16, // 右
			20,
			21,
			22,
			22,
			23,
			20, // 左
		];

		// 设置几何体属性
		geometry.setAttribute('position', new BufferAttribute(vertices, 3, false));
		geometry.setAttribute('normal', new BufferAttribute(normals, 3, true));
		geometry.setIndex(indices);

		return geometry;
	};

	useEffect(() => {
		// 初始化 Three.js 渲染器
		const canvas = canvasRef.current;
		if (!canvas) return;

		// 设置画布尺寸
		const width = canvas.clientWidth;
		const height = canvas.clientHeight;
		canvas.width = width;
		canvas.height = height;

		// 创建场景
		const scene = new Scene();
		sceneRef.current = scene;

		// 创建相机
		const camera = new PerspectiveCamera(75, width / height, 0.1, 1000);
		camera.position.z = 5;
		cameraRef.current = camera;
		camera.updateWorldMatrix(true, true);

		// 创建渲染器
		const renderer = new WebGLRenderer({ canvas, antialias: true });
		renderer.setSize(width, height);
		renderer.setPixelRatio(window.devicePixelRatio);
		rendererRef.current = renderer;

		// 方法1：使用 BoxGeometry（简单方式）
		// 创建立方体几何体
		const geometry = new BoxGeometry(2, 2, 2);

		// 创建材质 - 使用法线材质可以显示出立体效果
		const material = new MeshNormalMaterial({
			wireframe: false, // 设置为 true 可以显示线框
			transparent: false, // 是否透明
			opacity: 1.0, // 不透明度
			side: 2, // 显示所有面
		});

		// 创建网格（几何体+材质）
		const cube = new Mesh(geometry, material);
		scene.add(cube);
		cubeRef.current = cube;

		// 方法2：使用 BufferGeometry（自定义顶点方式）
		// 如果需要完全自定义顶点，可以使用以下代码
		const customGeometry = createCustomCubeGeometry();
		const customCube = new Mesh(customGeometry, material);
		scene.add(customCube);
		customCube.position.x = 3;

		// 添加轨道控制器，允许用户通过鼠标操作相机
		const controls = new OrbitControls(camera, renderer.domElement);
		controls.enableDamping = true; // 启用阻尼效果
		controls.dampingFactor = 0.05; // 阻尼系数
		controlsRef.current = controls;
		// console.log(camera.projectionMatrix);
		const modelMatrix = cube.matrixWorld;
		const viewMatrix = camera.matrixWorldInverse;
		const projectionMatrix = camera.projectionMatrix;

		// MVP = P × V × M
		const mvpMatrix = new Matrix4();
		mvpMatrix.multiplyMatrices(projectionMatrix, viewMatrix);
		mvpMatrix.multiply(modelMatrix); // 再乘以 model

		// 查看结果
		// console.log('MVP Matrix:', mvpMatrix);
		console.log('MVP Elements:', cube.rotation); // 打印 16 个数值

		// 动画循环
		const animate = () => {
			// 请求下一帧动画
			animationFrameRef.current = requestAnimationFrame(animate);

			// 更新控制器
			if (controlsRef.current) {
				controlsRef.current.update();
			}

			// 使立方体旋转
			if (cubeRef.current) {
				cubeRef.current.rotation.x += 0.005;
				cubeRef.current.rotation.y += 0.005;
			}

			// 渲染场景
			if (rendererRef.current && sceneRef.current && cameraRef.current) {
				rendererRef.current.render(sceneRef.current, cameraRef.current);
			}
		};

		// 开始动画
		animate();

		// 处理窗口大小变化
		const handleResize = () => {
			if (!canvas || !cameraRef.current || !rendererRef.current) return;

			const newWidth = canvas.clientWidth;
			const newHeight = canvas.clientHeight;

			canvas.width = newWidth;
			canvas.height = newHeight;

			// 更新相机宽高比
			cameraRef.current.aspect = newWidth / newHeight;
			cameraRef.current.updateProjectionMatrix();

			// 更新渲染器尺寸
			rendererRef.current.setSize(newWidth, newHeight);
		};

		// 添加窗口大小变化监听器
		window.addEventListener('resize', handleResize);

		// 清理函数
		return () => {
			if (animationFrameRef.current) {
				cancelAnimationFrame(animationFrameRef.current);
			}
			window.removeEventListener('resize', handleResize);

			// 清理 Three.js 对象
			if (controlsRef.current) {
				controlsRef.current.dispose();
			}
			if (rendererRef.current) {
				rendererRef.current.dispose();
			}
		};
	}, []);
}

function useCustomCanvas(
	canvasCustomRef: React.RefObject<HTMLCanvasElement | null>,
) {
	const animationFrameRef = useRef<number>(0);
	const controlsRef = useRef<OrbitControls | null>(null);
	function createCube(): { index: number[]; position: number[] } {
		const geometry = new BoxGeometry(2, 2, 2);
		return {
			index: geometry.index?.array || [],
			position: geometry.attributes.position.array,
		} as any;
	}
	useEffect(() => {
		if (!canvasCustomRef.current) return;
		const canvas = canvasCustomRef.current;
		canvas.width = window.innerWidth;
		canvas.height = window.innerHeight;
		// const controls = new OrbitControls(camera, renderer.domElement);
		// controls.enableDamping = true; // 启用阻尼效果
		// controls.dampingFactor = 0.05; // 阻尼系数
		// controlsRef.current = controls;
		const gl = canvas.getContext('webgl2')!;

		gl.enable(gl.DEPTH_TEST);
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
		gl.clearColor(0.1, 0.1, 0.1, 1.0);
		gl.viewport(0, 0, canvas.width, canvas.height);
		const vertexShader = GlUtil.createVertexShader(
			gl,
			`#version 300 es
			precision highp float;
			in vec3 aPosition;
			uniform mat4 uModel;
			uniform mat4 uView;
			uniform mat4 uProjection;
			out vec3 vPosition;
			void main() {
				vPosition = aPosition;
				gl_Position =vec4( uProjection * uView * uModel *  vec4(aPosition, 1.0));
			}
		`,
		)!;
		const fragmentShader = GlUtil.createFragmentShader(
			gl,
			`#version 300 es
			precision highp float;
			in vec3 vPosition;
			out vec4 FragColor;
			void main() {
				FragColor = vec4(0.5, 0.5, 1.0, 1.0);
			}
		`,
		)!;
		const program = GlUtil.createProgram(gl, vertexShader, fragmentShader);
		GlUtil.useProgram(gl, program);
		const { index, position } = createCube();
		// const indices = Array.from({length:position.length /= 3},(v,i) => i )
		// const colors = Array.from({length:position.length},(v,i) => i % 3 === 0 ? 1 : 0)
		const colors = Array.from({length:position.length/3},(v,i) => i)
		console.log(position);
		const positionBuffer = GlUtil.createBuffer(gl, position);
		GlUtil.setAttribute(gl, program, 'aPosition', positionBuffer, 3);
		const modelMatrix = getModeMatrix(1, 0, 0);
		const viewMatrix = getViewMatrix(new Vector3(0, 0, 5));
		const projectionMatrix = getPerspectiveViaOrthographic(
			45,
			canvas.width / canvas.height,
			0.1,
			1000,
		);
		GlUtil.setUniforms(gl, program, {
			uModel: modelMatrix.elements,
			uView: viewMatrix.elements,
			uProjection: projectionMatrix.elements,
		});
		const mvpMatrix = new Matrix4();
		mvpMatrix.multiplyMatrices(projectionMatrix, viewMatrix);
		mvpMatrix.multiply(modelMatrix);
		console.log(modelMatrix.elements);
		const indexBuffer = GlUtil.createIndexBuffer(gl, index);
		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
		gl.drawElements(gl.TRIANGLES, index.length, gl.UNSIGNED_SHORT, 0);
		let angle = 0;
		const animate = () => {
			// 请求下一帧动画
			animationFrameRef.current = requestAnimationFrame(animate);
			angle += 0.01;
			const modelMatrix = getModeMatrix(1, 0, angle);
			GlUtil.setUniforms(gl, program, {
				uModel: modelMatrix.elements,
				// uView: viewMatrix.elements,
				// uProjection: projectionMatrix.elements,
			});
			gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
			gl.drawElements(gl.TRIANGLES, index.length, gl.UNSIGNED_SHORT, 0);

			// 更新控制器
			// if (controlsRef.current) {
			// 	controlsRef.current.update();
			// }

			// 使立方体旋转
			// if (cubeRef.current) {
			// 	cubeRef.current.rotation.x += 0.005;
			// 	cubeRef.current.rotation.y += 0.005;
			// }

			// 渲染场景
			// if (rendererRef.current && sceneRef.current && cameraRef.current) {
			// 	rendererRef.current.render(sceneRef.current, cameraRef.current);
			// }
		};
		animate();
	}, []);
}
const ThreeJsCubeDemo = () => {
	// Canvas DOM 元素引用
	const canvasRef = useRef<HTMLCanvasElement>(null);
	const canvasCustomRef = useRef<HTMLCanvasElement>(null);
	useThreeJs(canvasRef);
	useCustomCanvas(canvasCustomRef);
	// Three.js 组件引用

	return (
		<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-4">
			<h1 className="text-2xl font-bold mb-4 text-gray-800">
				Three.js 立方体例程
			</h1>
			<div className="w-full bg-white p-4 rounded-lg shadow-lg">
				<div className="flex justify-between">
					<canvas
						ref={canvasRef}
						className="w-[500px] h-[500px]"
						// style={{ width: '100%', height: '500px' }}
					/>
					<canvas
						ref={canvasCustomRef}
						className="w-[500px] h-[500px] bg-gray-200"
						// style={{ width: '100%', height: '500px' }}
					></canvas>
				</div>
				<div className="mt-4 text-sm text-gray-600">
					<p>操作说明：</p>
					<ul className="list-disc pl-5 mt-1">
						<li>鼠标拖拽：旋转视图</li>
						<li>滚轮：缩放</li>
						<li>Shift+拖拽：平移视图</li>
					</ul>
				</div>
			</div>
		</div>
	);
};

export default ThreeJsCubeDemo;
